/*
 * TCSS 422, Project 2 (Scheduler Simulation)
 * Team 9 Name: blueraccoon422
 * Team 9 Group Members: Jacob Hall, Jacob Mertens, Diana Gorun, Alex Stringham
 * File Name: Process.c
 * Date: May 22, 2013
 */

#include <stdio.h>
#include <stdlib.h>
#include "Process.h"
#include  <unistd.h>
// The number of requests depending on process type.
int num_request(PROCESS_TYPE proc_type, int num_requests) {
	int num_req;
	//request = request * 5 for producer/consumer, because requesting memory access.
//      if (proc_type == PRODUCER_PROCESS || proc_type == CONSUMER_PROCESS) {
//              num_req = num_requests * 5;
	if (proc_type == CALCULATOR_PROCESS) { //calculator don't have request.
		num_req = 0;
	} else {
		num_req = num_requests;
	}
	return num_req;
}
RequestStr* request_array_init(PROCESS_TYPE process_type, int num_request,
		int num_steps) {
	RequestStr * requests;
	int i;
	requests = (RequestStr*) malloc(sizeof(RequestStr) * num_request);
	REQUEST_TYPE req_type;
	//each process type do this own request.calculator don't do request.
	if (process_type == AUXILIARY_PROCESS) {
		req_type = AUXILIARY_IO_REQUEST;
	} else if (process_type == KEYBOARD_PROCESS) {
		req_type = KEYBOARD_IO_REQUEST;
	} else if (process_type == CONSUMER_PROCESS) {
		req_type = CONSUMER_REQUEST;
	} else if (process_type == PRODUCER_PROCESS) {
		req_type = PRODUCER_REQUEST;
	} else {
		req_type = NO_REQUEST;
	}
	for (i = 0; i < num_request; i++) {
		requests[i].step = (rand() % num_steps) + 1;
		requests[i].request_type = req_type;
	}
	return requests;
}

// Initialize a process.
ProcessPtr process_init(int step, int num_req, RequestStr* requestArray,
		PROCESS_TYPE type_pro, char* name, int id, int memory_location,
		int priority, int ticketCount) {
	ProcessPtr process = (ProcessPtr) malloc(sizeof(ProcessStr));
	process->no_steps = step;
	process->no_requests = num_req;
	process->requests = requestArray;
	process->pro_type = type_pro;
	process->name = name;
	process->id = id;
	process->memory_location = memory_location;
	process->priority = priority;
	process->ticketCount = ticketCount;
	return process;
}
// Initialize the process table.
void PCB_init(ProcessPtr process,int next_step) {
	if (pcbTable == NULL ) {
		//TODO I am able to limit to 100 PCBs is that ok or do we need to explore something else?
		pcbTable = (PCBPtr) malloc(sizeof(PCBStr)*100);
	}
	pcbTable[process->id].next_step = next_step;

	if (scheduling == 0) {
		pcbTable[process->id].queue = ready_queue;
		add_queue(ready_queue, process->id);
	} else if (scheduling == 1) {
		pcbTable[process->id].queue = ready_queue;
		add_priority_queue(ready_queue, process->id, process->priority);
	}
	//printf("[%i]",process->id);
	pcbTable[process->id].process = process;
	pcbTable[process->id].state = RUNNABLE;
}
// Check if the current step produces a request.
REQUEST_TYPE is_request(ProcessStr* process, int step) {
	int i;
	for (i = 0; i < process->no_requests; i++) {
		if (process->requests[i].step == step)
			return process->requests[i].request_type;
	}
	return FALSE;
}

//detect keyboard interrupt.
void *keyboard() {
	//printf("\nkeyboard thread executing");
	int key, id;
	while (STOP != TRUE) {
		while (!queue_isEmpty(io_kb_queue)) {
			Node* temp = remove_queue(io_kb_queue);
			key = getch();
			//printf("\nkey %i has been pressed\n", key);
			//                      if(key != -1) {
			id = temp->PID;
			add_queue(interrupt_queue, id);
			printf("\nDevice 1 (Keyboard) produced an interrupt: %d\n", id);
		}
	}
	return NULL ;
}
//detect auxiliary, and generate interrupt if a device is waiting for it.
void *auxiliary() {
	int max, id;
	srand((unsigned) time(NULL ));
	while (!STOP) {
		//check to see if any process request for this device.
		while (!queue_isEmpty(auxiliary_queue)) {
			max = (rand() % (10)) + 5;
			printf("the random is %d", max);
			sleep(max);
			if (STOP)
				break;
			Node* temp = remove_queue(auxiliary_queue);
			id = temp->PID;
			add_queue(interrupt_queue, id);
			printf("\nDevice 2 (auxiliary) produced an interrupt: %d\n", id);
		}
	}
	return NULL ;
}

int getch() {
	/*
	 struct termios term_attr;
	 tcflag_t old_c_lflag;
	 int c;
	 tcgetattr(STDIN_FILENO, &term_attr);
	 old_c_lflag = term_attr.c_lflag;
	 term_attr.c_lflag &= ~(ICANON|ECHO);
	 tcsetattr(STDIN_FILENO, TCSANOW, &term_attr);
	 c = getchar();
	 term_attr.c_lflag = old_c_lflag;
	 tcsetattr(STDIN_FILENO, TCSANOW, &term_attr);
	 */
	return 0;
}
